
/**
 * date : 2018年2月25日
 * header, footer
 */
var header = '',
	footer = '';
var _t = new Date().getTime();
$.get(ctx+'/my/tpl/a102/header.html?t='+_t, function(_data){
	header = _data;
});
$.get(ctx+'/my/tpl/a102/footer.html?t='+_t, function(_data){
	footer = _data;
});

/**
 * 参考"my105_testPrintPageHeight.jsp"
 * 
 * 在以上页面可以测试页面的高度
 */
var PAGE_H = 1110;

/**
 * 2018年2月26日
 * 
 * 段落元素的`margin-top:0;margin-bottom:5px`
 */
var MARGIN_EXTRA = 5;

/**
 * 数组,按page划分
 * 每一个元素代表一页(填充到main(header,main,footer))
 */
var block_array = [];

/**
 * ue ifr
 * ifr101
 * ifr102
 * "header","footer"的高度(emr_headerH, emr_footerH)
 * 填充高度: pageMainH
 */
var ifrdoc = null,
	body = null,
	emrifrdoc1 = null,
	emrifrbody1 = null,
	emrifrdoc2 = null,
	emrifrbody2 = null,
	emr_headerH = 0,
	emr_footerH = 0,
	pageMainH = 0;

/**
 * `nonTableSplit`函数会使用此`seedId`变量
 */
var seedId = 1;

/**
 * date: 2018年2月23日
 * 
 * js循环遍历节点,并将纯文本包装(wrap)
 * 递归遍历元素节点,
 * (1)遇到文本节点,wrap;
 * (2)遇到标签递归,
 * 
 * [ typeof ](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof)
 * console.log( (typeof ele) , $(ele).text() );
 * 
 * update at 2018年2月27日, 优化代码,加入对`<p><br></p>`类型元素的判断
 * 
 */
var LoopInlineNodes = (function () {
	var regexp = new RegExp("(<.+?>).+(<\/.+?>)");
	var noCloseTagArr = ['br','hr'];// 这些元素可以不用闭合: br,hr,img,input,li,p
	var htmlStr = null;
    /**
     * 构造函数
     */
	function LoopInlineNodes() {
        htmlStr = '';
    }
    /**
     * 检查一个元素是否在一个数组中
     */
    function checkInArr(val, arr, ignoreCase){
    	var flag = false;
    	var val = val || '';
    	var arr = arr || [];
    	/**
    	 * var ignoreCase = ignoreCase || true;
    	 * 1) JS陷阱: 上面的代码是不可取的, 如果传入`false`计算的值也是true
    	 * var ignoreCase = (ignoreCase == undefined ? true : false);
    	 * 2) 上面的代码也是不可取的, 如果传入`true`计算的值也是false
    	 * var ignoreCase = (ignoreCase == undefined ? true : ignoreCase);
    	 * 3) 上面的写法才是正确的
    	 */
    	var ignoreCase = (ignoreCase === undefined ? true : ignoreCase);
    	var len = arr.length;
    	for(var i=0;i<len;i++){
    		if(ignoreCase){
    			if( val.toString().toUpperCase() === arr[i].toString().toUpperCase() ){
    				flag = true;
    				break;
    			}
    		}else{
    			if( val.toString() === arr[i].toString() ){
    				flag = true;
    				break;
    			}
    		}
    	}
    	return flag;
    }
    /**
     * 核心代码,递归
     */
    function _loop(ele){
        if (ele.nodeType === 3) {
        	var text = $(ele).text();
            var len = text.length;
            for (var i = 0; i < len; i++) {
                htmlStr += '<span class="emr">' + text[i] + '</span>';
            }
        }
        else {
            var startTag = '';
            var endTag = '';
            var tagName = $(ele).get(0).tagName;

            /**
             * 这里只考虑"br","hr"; img,input,li不用考虑
             */
            if( checkInArr(tagName,['br','hr']) ){
            	startTag = $(ele)[0].outerHTML;
            	endTag = '';
            }else{
            	if (regexp.test($(ele)[0].outerHTML)) {
                    startTag = RegExp.$1;
                    endTag = RegExp.$2;
                }
            }
            
            htmlStr += startTag;
            var contentsArr = $(ele).contents();
            if (contentsArr && contentsArr.length > 0) {
                $.each(contentsArr, function (i, n) {
                	_loop(n);
                });
            }
            htmlStr += endTag;
        }
    }
    LoopInlineNodes.prototype.getHtmlStr = function () {
        return htmlStr;
    };
    LoopInlineNodes.prototype.loop = function (ele) {
    	_loop(ele);
    };
    LoopInlineNodes.prototype.checkInArr = checkInArr;
    return LoopInlineNodes;
}());


/**
 * 检查一个元素是否在一个数组中
 * 
 * @param val
 * @param arr
 * @param ignoreCase
 * @returns {Boolean}
 */
function checkInArr(val, arr, ignoreCase){
	var flag = false;
	var val = val || '';
	var arr = arr || [];
	/**
	 * var ignoreCase = ignoreCase || true;
	 * 1) JS陷阱: 上面的代码是不可取的, 如果传入`false`计算的值也是true
	 * var ignoreCase = (ignoreCase == undefined ? true : false);
	 * 2) 上面的代码也是不可取的, 如果传入`true`计算的值也是false
	 * var ignoreCase = (ignoreCase == undefined ? true : ignoreCase);
	 * 3) 上面的写法才是正确的
	 */
	var ignoreCase = (ignoreCase === undefined ? true : ignoreCase);
	var len = arr.length;
	for(var i=0;i<len;i++){
		if(ignoreCase){
			if( val.toString().toUpperCase() === arr[i].toString().toUpperCase() ){
				flag = true;
				break;
			}
		}else{
			if( val.toString() === arr[i].toString() ){
				flag = true;
				break;
			}
		}
	}
	return flag;
}


$(function(){
	/**
	 * date: 2018年2月25日
	 * 
	 */
	$('#btnSplitAllEles').on('click', function(){
		var ue = UE.getEditor('editor');
		ifrdoc = ue.iframe.contentWindow.document;
		body = $('body', ifrdoc);
		
		var emriframe1 = $('#emriframe101');
		emrifrdoc1 = emriframe1[0].contentWindow.document;
		emrifrbody1 = $('body', emrifrdoc1);
		
		/**
		 * add at 2018年2月26日
		 */
		var emriframe2 = $('#emriframe102');
		emrifrdoc2 = emriframe2[0].contentWindow.document;
		emrifrbody2 = $('body', emrifrdoc2);
		
		/**
		 * important
		 * 给iframe的body元素设置width样式
		 */
		emrifrbody1.css('width', body.width());
		emrifrbody2.css('width', body.width());
		
		
		emrifrbody1.empty();
		emrifrbody1.append( header );
//		emrifrbody1.append( body[0].innerHTML );
		emrifrbody1.append( footer.replace('{{num}}', 1) );
		
		/**
		 * 取得"header","footer"的高度
		 */
		emr_headerH = emrifrbody1.find('div.emr_header').eq(0).outerHeight(true);
		emr_footerH = emrifrbody1.find('div.emr_footer').eq(0).outerHeight(true);
		
		/**
		 * 填充高度: pageMainH
		 * 用打印纸的高度减去(header和footer的高度之和),额外减去`5`像素的高度,作为当前页面的填充高度
		 */
		pageMainH = PAGE_H - (emr_headerH + emr_footerH) - 5;
		
		emrifrbody2.empty();
		emrifrbody2.append( body.get(0).innerHTML );
		
		loopFindBlockBreak();
		
		console.log( 'emr_header: ', emr_headerH );
		console.log( 'emr_footer: ', emr_footerH );
		
		// emriframe2[0].contentWindow.print();
		$('#emriframe102')[0].contentWindow.print();
		
	});
});




/**
 * date: 2018年2月26日
 * 
 * 递归调用
 * 
 */
function loopFindBlockBreak(){
	
	var _outerH = 0, prevN = null;
	var blockBreakN = null; //超出"填充高度"的那个元素(`BreakN`)
	/**
	 * 没有超出"填充高度"的元素的集合
	 */
	var blockList = [];
	/**
	 * `outerHTML`的集合
	 * 如果`block_array`没有元素就new一个数组,否则就取出block_array的最后一个元素.
	 * 
	 * var outerHtmlArr = (block_array.length == 0 ? [] : block_array[block_array.length-1]);
	 * 仔细思考后,发觉不用像上面那样. 
	 * 只有在成功拆分元素后,需要把上半部分放入到上一页. 下半部分不用管,随着递归的进行会自动得到处理!
	 * 那就是说: 需要取用上一页的数组向其中添加outerHTML,下一页(也即递归到这里)每次都是新new一个数组,直接`[]`即可!
	 */
	var outerHtmlArr = [];
	
	var prevH = 0; // `BreakN`的起始高度(与`position.top`(breakElePosition.top)有细微的差别)
	var breakElePosition = null; // `BreakN`的`position`
	/**
	 * 遍历子元素,找到超出"填充高度"的那个元素
	 * 将没有超出"填充高度"的元素收集起来
	 */
	$.each( emrifrbody2.children(), function(i,n){
		_outerH += $(n).outerHeight(true);
		if( _outerH > pageMainH ){
			blockBreakN = n;
			breakElePosition = $(n).position();
			return false;
		}
		blockList.push( n );
		prevN = n;
		prevH = _outerH;
	} );
	
	if(breakElePosition){
		console.log('breakElePosition: ', JSON.stringify(breakElePosition) );
		console.log('prevH: ', prevH);
	}
	
//	var strOuterHtml = ''; // `outerHTML`累加
//	/**
//	 * 将没有超出"填充高度"的所有元素的`outerHTML`累加起来之后,从doc中移除
//	 */
//	$.each(blockList, function(i,n){
//		strOuterHtml += $(n).get(0).outerHTML;
//		$(n).remove();
//	});
//	block_array.push( strOuterHtml );//将`strOuterHtml`放入全局对象`block_array`中!
	
	/**
	 * $(n).remove(); // important!!
	 */
	$.each(blockList, function(i,n){
		outerHtmlArr.push( $(n).get(0).outerHTML );
		$(n).remove(); // important!!
	});
	/**
	 * update at 2018年2月27日
	 * 直接将`blockList`这个数组放入`block_array`数组中！
	 * 这样,后续操作会更方便.
	 */
	block_array.push( blockList );
	
	if(blockBreakN){
		var blockTagName = $(blockBreakN)[0].tagName;
		
		console.log('== blockTagName ==', blockTagName);
		
		if('table'.toUpperCase() === blockTagName.toUpperCase()){
			console.log('table ...');
		}else{
			console.log('other ...');
			
			nonTableSplit( blockBreakN, prevH );
			
		}
	}
	
}

/**
 * date: 2018年2月27日
 * 
 * 处理非table元素的拆分！
 * 
 * @param blockBreakN 需要被拆分的元素(非table)
 * @param prevH `blockBreakN`在页面中的起始高度
 * @returns 
 * 
 */
function nonTableSplit(blockBreakN, prevH){
	console.log("== nonTableSplit ==");
	
	var blockBreakNouterHTML = null;
	
	var paragraph = null;
	var isSingleLine = false;
	
	var lin = null; // LoopInlineNodes
	var _newid = null;
	var emrArray = null;
	var len = null;
	var firstPos = null;
	var lastPos = null;
	
	/**
	 * 在ifr101中处理
	 */
	emrifrbody1.empty();
	blockBreakNouterHTML = $(blockBreakN).get(0).outerHTML;
	emrifrbody1.append( blockBreakNouterHTML );
	console.log( blockBreakNouterHTML );
	
	/**
	 * 不管是p元素还是其他的元素统一用"paragraph"来定义
	 */
	paragraph = emrifrbody1.children().eq(0);
	
	if(paragraph.attr('id')){}else{
		paragraph.attr('id', 'id_'+(seedId++));
	}
	
	/**
	 * `LoopInlineNodes`将所有字符添加`span.emr`标签
	 */
	lin = new LoopInlineNodes();
	lin.loop( paragraph.get(0) );
	_newid = paragraph.attr('id')+'_0'+(seedId++);
	paragraph.attr('id', _newid);
	$('#'+_newid, emrifrdoc1).before( lin.getHtmlStr() );
	console.log( lin.getHtmlStr() );
	$('#'+_newid, emrifrdoc1).remove();
	emrArray = emrifrbody1.find('span.emr');
	/**
	 * 新情况: <p><br></p>
	 * body.find('span.emr').length == 0
	 */
	if(emrArray.length == 0){
		// 此情况下,不用拆分. 也不用额外处理! `blockBreakN`随其他元素在下一次递归中被处理 
	}else{
		len = emrArray.length;
		console.log('len: ', len);
		var firstCharacter = $(emrArray[0]);
		firstPos = firstCharacter.position();
		var firstCharacterH = firstCharacter.outerHeight(true);
		lastPos = $(emrArray[len-1]).position();
		console.log("firstPos: ", firstPos);
		console.log("lastPos: ", lastPos);
		if(firstPos.top === lastPos.top){
			isSingleLine = true;
		}else{
			isSingleLine = false;
		}
		if(isSingleLine){
			// 此情况下,也不用拆分了,因为只有一行. 
		}else{
			var currentTop = firstPos.top; // (当前)`position.top`, y坐标
			var currentLineH = firstCharacterH; // (当前)行高
			if( prevH+currentLineH > pageMainH ){
				// 此情况下,也不用拆分了,因为第一行的高度大于剩余的高度.
			}else{
				$.each(emrArray, function(i,n){
					if( $(n).position().top > currentTop ){ // 这是换行后的第一个元素
						currentTop = $(n).position().top;
						currentLineH += $(n).outerHeight(true);
						if( prevH+currentLineH > pageMainH ){ // 找到拆分的位置点,插入自定义标记
							$(n).before('<span class="emrbreak"></span>');
							return false; // 退出`each`循环
						}
					}
				});
				//TODO: 找出'span.emrbreak'的所有父元素,将它们的startTag,endTag获取到,用正则表达式将它们分开! 应该先做测试
				// emrifrbody1.find('span.emrbreak').eq(0);
				var targetEle = emrifrbody1.children().eq(0);
				var startAndEndTagGather = getStartAndEndTagGather( targetEle );
				console.log('===startAndEndTagGather: ', startAndEndTagGather);
				var firstPartReg = new RegExp('(.*)(?=<span class="emrbreak"></span>)');
				var secondPartReg = new RegExp('(?<=<span class="emrbreak"></span>)(.*)');
				var firstPart = '', secondPart = '';
				if( firstPartReg.test(targetEle.get(0).outerHTML) ){
					firstPart = RegExp.$1;
				}
				if( secondPartReg.test(targetEle.get(0).outerHTML) ){
					secondPart = RegExp.$1;
				}
				firstPart = firstPart + startAndEndTagGather['endTagGather'];
				secondPart = startAndEndTagGather['startTagGather'] + secondPart;
				
				/**
				 * 将"上半部分"放入到上一页的数组中
				 */
				block_array[block_array.length-1].push(firstPart);
				/**
				 * 使用"下半部分"替换之前的标签内容
				 * important: 这时要使用`emrifrdoc2`, `emrifrbody2`
				 * //emrifrbody2.find(blockBreakNouterHTML);
				 */
				var targetBreakEle = $(blockBreakNouterHTML, emrifrdoc2);
				targetBreakEle.before( secondPart );
				targetBreakEle.remove();
				
				console.log('== firstPart ==');
				console.log( firstPart );
				console.log('== secondPart ==');
				console.log( secondPart );
			}
		}
		console.log('isSingleLine: ', isSingleLine);
	}
	
	
	
}




function getStartAndEndTagGather(targetEle){
//	var divTest = $('#test');
//	divTest.empty();
//	divTest.append('<p><span id="span002">现病史:<span>患者于<b>半年余前</b>无明显诱因下出现右上腹部疼痛，</span>呈持续性闷痛，逐渐<b>加重，<span class="emrbreak"></span>开始</b>无伴有皮肤黄染，未呈桔黄色，无尿色变黄，无呈浓茶样改变</span></p>');
//	var targetEle = divTest.children().eq(0);
	
	var regexp = new RegExp("(<.+?>).+(<\/.+?>)");
	
	var emrbreak = targetEle.find('span.emrbreak').eq(0);
	console.log('== emrbreak ==');
	console.log(emrbreak);
	var allNecessaryParents = [];
	/**
	 * API: http://api.jquery.com/parents/
	 * 
	 * `parents()`会将'body','html'都拿出来
	 */
	$.each(emrbreak.parents(), function(i,n){
		if(!checkInArr($(n).get(0).tagName, ['body','html'])){
			allNecessaryParents.push( n );
		}
	});
	var len = allNecessaryParents.length;
	var startTagGather = '', endTagGather = '';
	var endTagArr = [];
	for(var i=len-1; i>=0; i--){
		//console.log( allNecessaryParents[i] );
    	if (regexp.test($(allNecessaryParents[i])[0].outerHTML)) {
    		startTagGather += RegExp.$1;
    		endTagArr.push(RegExp.$2);
        }
	}
	var len2 = endTagArr.length;
	for(var j=len2-1; j>=0; j--){
		endTagGather += endTagArr[j];
	}
	console.log('startTagGather: ', startTagGather);
	console.log('endTagGather: ', endTagGather);
	return {"startTagGather":startTagGather, "endTagGather":endTagGather};
}



















